@@ -25,13 +25,15 @@ class Agent < ActiveRecord::Base |
||
25 | 25 |
|
26 | 26 |
EVENT_RETENTION_SCHEDULES = [["Forever", 0], ["1 day", 1], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n] })] |
27 | 27 |
|
28 |
- attr_accessible :options, :memory, :name, :type, :schedule, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately |
|
28 |
+ attr_accessible :options, :memory, :name, :type, :schedule, :runner_ids, :target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately |
|
29 | 29 |
|
30 | 30 |
json_serialize :options, :memory |
31 | 31 |
|
32 | 32 |
validates_presence_of :name, :user |
33 | 33 |
validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last) |
34 | 34 |
validate :sources_are_owned |
35 |
+ validate :runners_are_owned |
|
36 |
+ validate :targets_are_owned |
|
35 | 37 |
validate :scenarios_are_owned |
36 | 38 |
validate :validate_schedule |
37 | 39 |
validate :validate_options |
@@ -52,6 +54,10 @@ class Agent < ActiveRecord::Base |
||
52 | 54 |
has_many :links_as_receiver, :dependent => :delete_all, :foreign_key => "receiver_id", :class_name => "Link", :inverse_of => :receiver |
53 | 55 |
has_many :sources, :through => :links_as_receiver, :class_name => "Agent", :inverse_of => :receivers |
54 | 56 |
has_many :receivers, :through => :links_as_source, :class_name => "Agent", :inverse_of => :sources |
57 |
+ has_many :chains_as_runner, dependent: :delete_all, foreign_key: 'runner_id', class_name: 'Chain', inverse_of: :runner |
|
58 |
+ has_many :chains_as_target, dependent: :delete_all, foreign_key: 'target_id', class_name: 'Chain', inverse_of: :target |
|
59 |
+ has_many :runners, through: :chains_as_target, class_name: "Agent", inverse_of: :targets |
|
60 |
+ has_many :targets, through: :chains_as_runner, class_name: "Agent", inverse_of: :runners |
|
55 | 61 |
has_many :scenario_memberships, :dependent => :destroy, :inverse_of => :agent |
56 | 62 |
has_many :scenarios, :through => :scenario_memberships, :inverse_of => :agents |
57 | 63 |
|
@@ -218,6 +224,14 @@ class Agent < ActiveRecord::Base |
||
218 | 224 |
errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user == user } |
219 | 225 |
end |
220 | 226 |
|
227 |
+ def runners_are_owned |
|
228 |
+ errors.add(:runners, "must be owned by you") unless runners.all? {|s| s.user == user } |
|
229 |
+ end |
|
230 |
+ |
|
231 |
+ def targets_are_owned |
|
232 |
+ errors.add(:targets, "must be owned by you") unless targets.all? {|s| s.user == user } |
|
233 |
+ end |
|
234 |
+ |
|
221 | 235 |
def scenarios_are_owned |
222 | 236 |
errors.add(:scenarios, "must be owned by you") unless scenarios.all? {|s| s.user == user } |
223 | 237 |
end |
@@ -249,7 +263,7 @@ class Agent < ActiveRecord::Base |
||
249 | 263 |
|
250 | 264 |
class << self |
251 | 265 |
def build_clone(original) |
252 |
- new(original.slice(:type, :options, :schedule, :source_ids, :keep_events_for, :propagate_immediately)) { |clone| |
|
266 |
+ new(original.slice(:type, :options, :schedule, :runner_ids, :source_ids, :keep_events_for, :propagate_immediately)) { |clone| |
|
253 | 267 |
# Give it a unique name |
254 | 268 |
2.upto(count) do |i| |
255 | 269 |
name = '%s (%d)' % [original.name, i] |
@@ -399,6 +413,8 @@ class AgentDrop |
||
399 | 413 |
:sources, |
400 | 414 |
:receivers, |
401 | 415 |
:schedule, |
416 |
+ :runners, |
|
417 |
+ :targets, |
|
402 | 418 |
:disabled, |
403 | 419 |
:keep_events_for, |
404 | 420 |
:propagate_immediately, |
@@ -0,0 +1,7 @@ |
||
1 |
+# A Chain connects Agents in a run chain from the `runner` to the `target`. |
|
2 |
+class Chain < ActiveRecord::Base |
|
3 |
+ attr_accessible :runner_id, :target_id |
|
4 |
+ |
|
5 |
+ belongs_to :runner, class_name: 'Agent', inverse_of: :chains_as_runner |
|
6 |
+ belongs_to :target, class_name: 'Agent', inverse_of: :chains_as_target |
|
7 |
+end |
@@ -0,0 +1,13 @@ |
||
1 |
+class CreateChains < ActiveRecord::Migration |
|
2 |
+ def change |
|
3 |
+ create_table :chains do |t| |
|
4 |
+ t.integer :runner_id |
|
5 |
+ t.integer :target_id |
|
6 |
+ |
|
7 |
+ t.timestamps |
|
8 |
+ end |
|
9 |
+ |
|
10 |
+ add_index :chains, [:runner_id, :target_id], unique: true |
|
11 |
+ add_index :chains, :target_id |
|
12 |
+ end |
|
13 |
+end |
@@ -11,7 +11,7 @@ |
||
11 | 11 |
# |
12 | 12 |
# It's strongly recommended that you check this file into your version control system. |
13 | 13 |
|
14 |
-ActiveRecord::Schema.define(version: 20140605032822) do |
|
14 |
+ActiveRecord::Schema.define(version: 20140821155428) do |
|
15 | 15 |
|
16 | 16 |
create_table "agent_logs", force: true do |t| |
17 | 17 |
t.integer "agent_id", null: false |
@@ -50,6 +50,16 @@ ActiveRecord::Schema.define(version: 20140605032822) do |
||
50 | 50 |
add_index "agents", ["type"], name: "index_agents_on_type", using: :btree |
51 | 51 |
add_index "agents", ["user_id", "created_at"], name: "index_agents_on_user_id_and_created_at", using: :btree |
52 | 52 |
|
53 |
+ create_table "chains", force: true do |t| |
|
54 |
+ t.integer "runner_id" |
|
55 |
+ t.integer "target_id" |
|
56 |
+ t.datetime "created_at" |
|
57 |
+ t.datetime "updated_at" |
|
58 |
+ end |
|
59 |
+ |
|
60 |
+ add_index "chains", ["runner_id", "target_id"], name: "index_chains_on_runner_id_and_target_id", unique: true, using: :btree |
|
61 |
+ add_index "chains", ["target_id"], name: "index_chains_on_target_id", using: :btree |
|
62 |
+ |
|
53 | 63 |
create_table "delayed_jobs", force: true do |t| |
54 | 64 |
t.integer "priority", default: 0 |
55 | 65 |
t.integer "attempts", default: 0 |
@@ -486,7 +486,7 @@ describe Agent do |
||
486 | 486 |
agent.errors_on(:options).should include("cannot be set to an instance of Fixnum") |
487 | 487 |
end |
488 | 488 |
|
489 |
- it "should not allow agents owned by other people" do |
|
489 |
+ it "should not allow source agents owned by other people" do |
|
490 | 490 |
agent = Agents::SomethingSource.new(:name => "something") |
491 | 491 |
agent.user = users(:bob) |
492 | 492 |
agent.source_ids = [agents(:bob_weather_agent).id] |
@@ -497,6 +497,28 @@ describe Agent do |
||
497 | 497 |
agent.should have(0).errors_on(:sources) |
498 | 498 |
end |
499 | 499 |
|
500 |
+ it "should not allow runner agents owned by other people" do |
|
501 |
+ agent = Agents::SomethingSource.new(:name => "something") |
|
502 |
+ agent.user = users(:bob) |
|
503 |
+ agent.runner_ids = [agents(:bob_weather_agent).id] |
|
504 |
+ agent.should have(0).errors_on(:runners) |
|
505 |
+ agent.runner_ids = [agents(:jane_weather_agent).id] |
|
506 |
+ agent.should have(1).errors_on(:runners) |
|
507 |
+ agent.user = users(:jane) |
|
508 |
+ agent.should have(0).errors_on(:runners) |
|
509 |
+ end |
|
510 |
+ |
|
511 |
+ it "should not allow target agents owned by other people" do |
|
512 |
+ agent = Agents::CannotBeScheduled.new(:name => "something") |
|
513 |
+ agent.user = users(:bob) |
|
514 |
+ agent.target_ids = [agents(:bob_weather_agent).id] |
|
515 |
+ agent.should have(0).errors_on(:targets) |
|
516 |
+ agent.target_ids = [agents(:jane_weather_agent).id] |
|
517 |
+ agent.should have(1).errors_on(:targets) |
|
518 |
+ agent.user = users(:jane) |
|
519 |
+ agent.should have(0).errors_on(:targets) |
|
520 |
+ end |
|
521 |
+ |
|
500 | 522 |
it "should not allow scenarios owned by other people" do |
501 | 523 |
agent = Agents::SomethingSource.new(:name => "something") |
502 | 524 |
agent.user = users(:bob) |